package org.jeecg.modules.tls.blog.comment.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.StringUtils;
import org.jeecg.common.exception.JeecgBootException;
import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.common.util.oConvertUtils;
import org.jeecg.common.system.vo.SelectTreeModel;
import org.jeecg.modules.system.entity.SysUser;
import org.jeecg.modules.system.service.ISysUserService;
import org.jeecg.modules.tls.blog.article.vo.PageVo;
import org.jeecg.modules.tls.blog.comment.entity.BlogComment;
import org.jeecg.modules.tls.blog.comment.mapper.BlogCommentMapper;
import org.jeecg.modules.tls.blog.comment.service.IBlogCommentService;
import org.jeecg.modules.tls.blog.comment.vo.BlogCommentVo;
import org.jeecg.modules.tls.blog.common.AppHttpCodeEnum;
import org.jeecg.modules.tls.blog.common.ResponseResult;
import org.jeecg.modules.tls.blog.utils.BeanCopyUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

/**
 * @Description: 博客评论
 * @Author: jeecg-boot
 * @Date:   2023-03-10
 * @Version: V1.0
 */
@Service
public class BlogCommentServiceImpl extends ServiceImpl<BlogCommentMapper, BlogComment> implements IBlogCommentService {

    @Autowired
    private ISysUserService sysUserService;

	@Override
	public void addBlogComment(BlogComment blogComment) {
        //新增时设置hasChild为0
	    blogComment.setHasChild(IBlogCommentService.NOCHILD);
		if(oConvertUtils.isEmpty(blogComment.getPid())){
			blogComment.setPid(IBlogCommentService.ROOT_PID_VALUE);
		}else{
			//如果当前节点父ID不为空 则设置父节点的hasChildren 为1
			BlogComment parent = baseMapper.selectById(blogComment.getPid());
			if(parent!=null && !"1".equals(parent.getHasChild())){
				parent.setHasChild("1");
				baseMapper.updateById(parent);
			}
		}
		baseMapper.insert(blogComment);
	}

    @Override
    public ResponseResult addComment(BlogComment blogComment) {
        //获取当前用户id
        Subject subject = SecurityUtils.getSubject();
        LoginUser userNow = (LoginUser) subject.getPrincipal();
        String id = userNow.getId();

        //新增时设置hasChild为0
        blogComment.setHasChild(IBlogCommentService.NOCHILD);


        blogComment.setUserId(id);


        //评论内容不能为空
        if(!StringUtils.hasText(blogComment.getCommentContent())){
            return ResponseResult.errorResult(AppHttpCodeEnum.CONTENT_NOT_NULL);
        }

        if(oConvertUtils.isEmpty(blogComment.getPid())){
            blogComment.setPid(IBlogCommentService.ROOT_PID_VALUE);
        }else{
            //如果当前节点父ID不为空 则设置父节点的hasChildren 为1
            BlogComment parent = baseMapper.selectById(blogComment.getPid());
            if(parent!=null && !"1".equals(parent.getHasChild())){
                parent.setHasChild("1");
                baseMapper.updateById(parent);
            }
        }
        baseMapper.insert(blogComment);
        return ResponseResult.okResult();
    }
	
	@Override
	public void updateBlogComment(BlogComment blogComment) {
		BlogComment entity = this.getById(blogComment.getId());
		if(entity==null) {
			throw new JeecgBootException("未找到对应实体");
		}
		String old_pid = entity.getPid();
		String new_pid = blogComment.getPid();
		if(!old_pid.equals(new_pid)) {
			updateOldParentNode(old_pid);
			if(oConvertUtils.isEmpty(new_pid)){
				blogComment.setPid(IBlogCommentService.ROOT_PID_VALUE);
			}
			if(!IBlogCommentService.ROOT_PID_VALUE.equals(blogComment.getPid())) {
				baseMapper.updateTreeNodeStatus(blogComment.getPid(), IBlogCommentService.HASCHILD);
			}
		}
		baseMapper.updateById(blogComment);
	}

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteBlogComment(String id) throws JeecgBootException {
        //查询选中节点下所有子节点一并删除
        id = this.queryTreeChildIds(id);
        if(id.indexOf(",")>0) {
            StringBuffer sb = new StringBuffer();
            String[] idArr = id.split(",");
            for (String idVal : idArr) {
                if(idVal != null){
                    BlogComment blogComment = this.getById(idVal);
                    String pidVal = blogComment.getPid();
                    //查询此节点上一级是否还有其他子节点
                    List<BlogComment> dataList = baseMapper.selectList(new QueryWrapper<BlogComment>().eq("pid", pidVal).notIn("id",Arrays.asList(idArr)));
                    boolean flag = (dataList == null || dataList.size() == 0) && !Arrays.asList(idArr).contains(pidVal) && !sb.toString().contains(pidVal);
                    if(flag){
                        //如果当前节点原本有子节点 现在木有了，更新状态
                        sb.append(pidVal).append(",");
                    }
                }
            }
            //批量删除节点
            baseMapper.deleteBatchIds(Arrays.asList(idArr));
            //修改已无子节点的标识
            String[] pidArr = sb.toString().split(",");
            for(String pid : pidArr){
                this.updateOldParentNode(pid);
            }
        }else{
            BlogComment blogComment = this.getById(id);
            if(blogComment==null) {
                throw new JeecgBootException("未找到对应实体");
            }
            updateOldParentNode(blogComment.getPid());
            baseMapper.deleteById(id);
        }
    }
	
	@Override
    public List<BlogComment> queryTreeListNoPage(QueryWrapper<BlogComment> queryWrapper) {
        List<BlogComment> dataList = baseMapper.selectList(queryWrapper);
        List<BlogComment> mapList = new ArrayList<>();
        for(BlogComment data : dataList){
            String pidVal = data.getPid();
            //递归查询子节点的根节点
            if(pidVal != null && !IBlogCommentService.NOCHILD.equals(pidVal)){
                BlogComment rootVal = this.getTreeRoot(pidVal);
                if(rootVal != null && !mapList.contains(rootVal)){
                    mapList.add(rootVal);
                }
            }else{
                if(!mapList.contains(data)){
                    mapList.add(data);
                }
            }
        }
        return mapList;
    }

    @Override
    public List<SelectTreeModel> queryListByCode(String parentCode) {
        String pid = ROOT_PID_VALUE;
        if (oConvertUtils.isNotEmpty(parentCode)) {
            LambdaQueryWrapper<BlogComment> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(BlogComment::getPid, parentCode);
            List<BlogComment> list = baseMapper.selectList(queryWrapper);
            if (list == null || list.size() == 0) {
                throw new JeecgBootException("该编码【" + parentCode + "】不存在，请核实!");
            }
            if (list.size() > 1) {
                throw new JeecgBootException("该编码【" + parentCode + "】存在多个，请核实!");
            }
            pid = list.get(0).getId();
        }
        return baseMapper.queryListByPid(pid, null);
    }

    @Override
    public List<SelectTreeModel> queryListByPid(String pid) {
        if (oConvertUtils.isEmpty(pid)) {
            pid = ROOT_PID_VALUE;
        }
        return baseMapper.queryListByPid(pid, null);
    }

    @Override
    public ResponseResult commentList(String articleId, Integer pageNum, Integer pageSize) {
        //查询对应文章的根评论
        LambdaQueryWrapper<BlogComment> queryWrapper = new LambdaQueryWrapper<>();
        //对articleId进行判断
        queryWrapper.eq(BlogComment::getArticleId,articleId);
        queryWrapper.eq(BlogComment::getRootId,-1);
        //分页查询
        Page<BlogComment> page = new Page(pageNum,pageSize);
        page(page,queryWrapper);

        List<BlogCommentVo> commentVoList = toBlogCommentVoList(page.getRecords());

        //查询所有根评论对应的子评论集合，并且赋值给对应的属性
        for (BlogCommentVo blogCommentVo : commentVoList) {
            //查询对应的子评论
            List<BlogCommentVo> children = getChildren(blogCommentVo.getId());
            //赋值
            blogCommentVo.setChildren(children);
        }

        return ResponseResult.okResult(new PageVo(commentVoList,page.getTotal()));
    }



    /**
     * 根据根评论的id查询所对应的子评论的集合
     * @param id 根评论的id
     * @return
     */
    private List<BlogCommentVo> getChildren(String id) {

        LambdaQueryWrapper<BlogComment> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(BlogComment::getRootId,id);
        queryWrapper.orderByAsc(BlogComment::getCreateTime);
        List<BlogComment> comments = list(queryWrapper);

        List<BlogCommentVo> blogCommentVos = new ArrayList<>();


        //遍历vo集合
        for (BlogComment blogComment : comments) {
            BlogCommentVo blogCommentVo = new BlogCommentVo();
            BeanUtils.copyProperties(blogComment, blogCommentVo);
            //通过creatyBy查询用户的昵称并赋值
            String realname = sysUserService.getById(blogCommentVo.getUserId()).getRealname();
            String avatar = sysUserService.getById(blogCommentVo.getUserId()).getAvatar();
            String pid = blogComment.getPid();
            for(BlogComment blogCommentChild: comments){
                if(blogCommentChild.getId().equals(pid)){
                    String userId = blogCommentChild.getUserId();
                    SysUser user = sysUserService.getById(userId);
                    blogCommentVo.setUsernameParent(user.getUsername());
                }
            }
            blogCommentVos.add(blogCommentVo);
            blogCommentVo.setUsername(realname);
            blogCommentVo.setAvatar(avatar);

        }
        return blogCommentVos;
    }

    private List<BlogCommentVo> toBlogCommentVoList(List<BlogComment> list){
        List<BlogCommentVo> blogCommentVos = BeanCopyUtils.copyBeanList(list, BlogCommentVo.class);
        //遍历vo集合
        for (BlogCommentVo blogCommentVo : blogCommentVos) {

//            if(blogCommentVo.getUserId())
            //通过creatyBy查询用户的昵称并赋值
            String realname = sysUserService.getById(blogCommentVo.getUserId()).getRealname();
            String avatar = sysUserService.getById(blogCommentVo.getUserId()).getAvatar();

            blogCommentVo.setUsername(realname);
            blogCommentVo.setAvatar(avatar);
        }
        return blogCommentVos;
    }


    /**
	 * 根据所传pid查询旧的父级节点的子节点并修改相应状态值
	 * @param pid
	 */
	private void updateOldParentNode(String pid) {
		if(!IBlogCommentService.ROOT_PID_VALUE.equals(pid)) {
			Long count = baseMapper.selectCount(new QueryWrapper<BlogComment>().eq("pid", pid));
			if(count==null || count<=1) {
				baseMapper.updateTreeNodeStatus(pid, IBlogCommentService.NOCHILD);
			}
		}
	}

	/**
     * 递归查询节点的根节点
     * @param pidVal
     * @return
     */
    private BlogComment getTreeRoot(String pidVal){
        BlogComment data =  baseMapper.selectById(pidVal);
        if(data != null && !IBlogCommentService.ROOT_PID_VALUE.equals(data.getPid())){
            return this.getTreeRoot(data.getPid());
        }else{
            return data;
        }
    }

    /**
     * 根据id查询所有子节点id
     * @param ids
     * @return
     */
    private String queryTreeChildIds(String ids) {
        //获取id数组
        String[] idArr = ids.split(",");
        StringBuffer sb = new StringBuffer();
        for (String pidVal : idArr) {
            if(pidVal != null){
                if(!sb.toString().contains(pidVal)){
                    if(sb.toString().length() > 0){
                        sb.append(",");
                    }
                    sb.append(pidVal);
                    this.getTreeChildIds(pidVal,sb);
                }
            }
        }
        return sb.toString();
    }

    /**
     * 递归查询所有子节点
     * @param pidVal
     * @param sb
     * @return
     */
    private StringBuffer getTreeChildIds(String pidVal,StringBuffer sb){
        List<BlogComment> dataList = baseMapper.selectList(new QueryWrapper<BlogComment>().eq("pid", pidVal));
        if(dataList != null && dataList.size()>0){
            for(BlogComment tree : dataList) {
                if(!sb.toString().contains(tree.getId())){
                    sb.append(",").append(tree.getId());
                }
                this.getTreeChildIds(tree.getId(),sb);
            }
        }
        return sb;
    }

}
